import moment from "moment/moment";
import {
  indexPredict,
  indexPredictKngc,
  indexSearch,
  indexSearchKngc,
  feedBack,
  tableDownload,
  tableDownloadKngc,
  addDialogue,
  dialogueInfo,
  dialogueList,
  editDialogue,
  editDialogue2,
  getTop5,
  filePreviewDownload
} from "@/services/intellectAssistant";
import {message} from "antd";
import Cookie from '@/utils/cookie.js';
let addLock=false
function downloadFileStream(fileData, filename) {
  const blob = new Blob([fileData], { type: fileData.type })
  if ('download' in document.createElement('a')) {
    const link = document.createElement('a')
    link.download = filename
    link.style.display = 'none'
    link.href = URL.createObjectURL(blob)
    document.body.appendChild(link)
    link.click()
    URL.revokeObjectURL(link.href)
    document.body.removeChild(link)
  } else {
    navigator.msSaveBlob(blob, filename)
  }
}
const errMsg={
  "A00001":"日期校验失败",
  "A00002":"未包含查询维度",
  "A00003":"账期校验失败",
  "A00004":"省份校验失败",
  "A00005":"获取数据失败",
  "A00006":"sql生成失败",
  "A00007":"不能包含多个计算指标",
  "A00008":"数据查询为空",
  "A00009":"获取虚拟宽表数据失败",
  "A00010":"已存在指标日志未具备",
  "A00011":"已存在明细表日志未具备",
  "A00012":"维度已验证无法删除",
  "A00013":"计算表达式错误",
  "A00014":"拍照指标表达式有误",
  "A00015":"计算指标表达式有误",
  "A88888":"下游返回错误的返回",
  "A99997":"请求格式错误",
  "A99998":"请求格式错误",
  "C10000":"请求格式错误",
  "C10001":"请求服务标识错误",
  "C10002":"请求能力标识错误",
  "N20000":"能力调用超时",
  "A00018":"数据鉴权为空 该数据未获取查询权限 ",

}
const IntellectAssistant = {
  namespace: 'intellectAssistant',
  state: {
    messageList: [],
    indexPredictData:{}, //预查询弹窗数据
    dialogueList: {}, // 历史会话列表
    dialogueOneInfo: [], // 点击历史会话的某一条
    dialogueId:"",//会话id
    dialogueIdGz:"",//会话id
    dialogueIdAI:"",//会话id
    title:"新会话",//会话名称
    titleGz:"新会话",
    titleAI:"新会话",
    top5List:[],
    isLoading:false,
    managementName:"维度管理",
    hotQuestion:[],
    dialogFlag:"0",//页签id
    backMessageListGz:[],//规则取数备份数据
    backMessageListAI:[],//AI取数备份数据
    userId:"",
    pageContent:[],//参考资料
    checkedSwitch:false,
    pageFileList:[],//文件列表
    tenantId:"", //权限标识
  },
  effects: {
    *getTop5Hot(_, { call,put }) {
      const res = yield call(getTop5)
      if(res&&res.code === 200) {
        // let arr = res.data.map(item => item.resp)
        yield put({
          type: 'updateState',
          payload: {
            hotQuestion: res.data,
          },
        })
      }
    },
    //指标预查询
    *fetchIndexPredictSearch({ payload,callback }, { call, put, select }) {
      const dataList = yield select(state => state.intellectAssistant.messageList)
      const isLoading = yield select(state => state.intellectAssistant.isLoading)
      const question = dataList[dataList.length-1].resp
      const newCreateTime = dataList[dataList.length-1].createTime;
      const dialogFlag = yield select(state => state.intellectAssistant.dialogFlag);
      const id = yield select(state => state.intellectAssistant.dialogueId);
      const userId = Cookie.get("userId");
      const tenantId = yield select(state => state.intellectAssistant.tenantId);
      let res=null
      try{
        if(dialogFlag==="0"){
          res = yield call(indexPredict, {...payload,userId,tenantId})
        }else if(dialogFlag==="1"){
          let formData = new FormData();
          for(let key in payload){
            if(key==="files"&&payload["files"]) {
              for(let item of payload[key] )
              formData.append("files", item);
            }else if(payload[key] !== undefined){
              formData.append(key, payload[key]);
            }
          }
          formData.append("userId", userId);
          formData.append("tenantId", tenantId);
          res = yield call(indexPredictKngc,formData)
        }
      }
      catch(error){
        if(error.message!=="canceled"){
          yield put({
            type: 'updateState',
            payload: {
              isLoading:false,
            },
          })
        }
      }
      const createTime = moment().format('YYYY-MM-DD    HH:mm:ss');
      let codeInformation =res?.resp_code.startsWith('0')?undefined:errMsg[res?.resp_code]?errMsg[res.resp_code]:'未知错误！'
      if(res){
        yield put({
          type: 'addMessageListState',
          payload: {
            resp: res||"",
            character: 'robot',
            createTime: createTime,
            predictStatus:true,
            codeInformation,
            question,
          },
          callback:()=>{},
          newCreateTime:newCreateTime
        });
        if(dialogFlag==="1") {
          yield put({
            type: 'updateState',
            payload: {
              pageContent:res?.page_content||[],
              checkedSwitch:res?.page_content?.length>0?true:false,
            },
          })
        }
        if(isLoading){
          yield put({
            type: 'updateState',
            payload: {
              isLoading:false,
            },
          })
        }

        while(addLock){
          yield new Promise(resolve=>setTimeout(resolve,50))
        }
        let params = {
          sender:Cookie.get('userName'),
          dialogueId:id,
          question:dataList.length-1,
          answer:{
            resp: res||"",
            character: 'robot',
            createTime: createTime,
            predictStatus:true,
            codeInformation,
            question,
          },
        }
        yield put({
          type: 'fetchAddLog',
          payload:params,
        })
      }else {
        yield put({
          type: 'updateState',
          payload: {
            pageContent:[],
            checkedSwitch: false,
          },
        })
        console.log("请求错误或请求取消")
      }
      if(isLoading&&res!==null){
        yield put({
          type: 'updateState',
          payload: {
            isLoading:false,
          },
        })
      }
    },

    //指标查询
    *fetchInformationData({ payload, callback }, { call, put, select }) {
      const dataList = yield select(state => state.intellectAssistant.messageList)
      const dialogueId= yield select(state => state.intellectAssistant.dialogueId)
      const question = JSON.parse(payload.question);
      const dialogFlag = yield select(state => state.intellectAssistant.dialogFlag)
      const userId = Cookie.get("userId");
      const tenantId = yield select(state => state.intellectAssistant.tenantId)
      let res=null
      let form=new FormData()
      form.append("name",question.replace(/[+\-*/=]/g, match => encodeURIComponent(match)))
      form.append("final_kpi_sql",payload?.resp?.final_kpi_sql||"")
      form.append("kpi_sql",payload?.resp?.kpi_sql||"")
      form.append("vtable_sql",payload?.resp?.vtable_sql||"")
      form.append("dialogueId",dialogueId)
      form.append("userId",userId)
      form.append("tenantId",tenantId)

      let form1 = new FormData()
      form1.append("name",question.replace(/[+\-*/=]/g, match => encodeURIComponent(match)))
      form1.append("kpi_sql",payload?.resp?.ai_sql||"")
      form1.append("dialogueId",dialogueId)
      form1.append("userId",userId)
      form1.append("tenantId",tenantId)
      try {
        if(dialogFlag==="0"){
          res = yield call(indexSearch,form);
        }else if(dialogFlag==="1"){
          //AI取数保留规则分析的功能，所以除 00006是大模型特有，其他的还是按照先前的传参，只是后端返回的结果来源不同
          if(payload?.resp?.resp_code==="00006"){
            res = yield call(indexSearchKngc,form1);
          }else {
            res = yield call(indexSearchKngc,form);
          }
        }
      } catch (e) {
        callback({error:true})
        yield put({
          type: 'updateState',
          payload: {
            isLoading:false,
          },
        })
        return
      }
      const createTime = moment().format('YYYY-MM-DD    HH:mm:ss');
      if(res){
        yield put({
          type: 'addMessageListState',
          payload: {
            resp: res,
            character: 'robot',
            createTime: createTime,
            question,
          },
        });
        let params = {
          sender:Cookie.get('userName'),
          dialogueId:dialogueId,
          question:dataList.length,
          answer:{
            resp: res,
            character: 'robot',
            createTime: createTime,
            question,
          },
        }
        if(callback) callback(params)
      }else {
        console.log("请求错误或请求取消")
      }
      yield put({
        type: 'updateState',
        payload: {
          isLoading:false,
        },
      })
    },
    //指点赞
    *fetchFeedBack({ payload,callback }, { call, put, select }) {
      const dialogFlag = yield select(state => state.intellectAssistant.dialogFlag)
      let res=null
      try{
        res = yield call(feedBack, {...payload,dialogFlag})
      }catch{
        return
      }
      const messageList = yield select(state => state.intellectAssistant.messageList)
      const answer = {...messageList[payload.index],islike:payload.islike}
      let data = JSON.parse(payload.answer)
      if(res==='成功'&&data.question!==""&&data.answer!==""){
        const dialogueId= yield select(state => state.intellectAssistant.dialogueId)
        let res=null
        try{
          res = yield call(editDialogue2,{
            sender:Cookie.get('userName'),
            question:payload.index,
            answer:JSON.stringify(answer),
            dialogueId
          })
        }catch{
          return
        }
        //响应结果不知道是什么
        if(callback) callback()
      }else{
        message.error('反馈失败')
      }
    },
    //下载
    *fetchTableDownload({ payload }, { call, put,select }) {
      const dialogFlag = yield select(state => state.intellectAssistant.dialogFlag);
      const tenantId = yield select(state => state.intellectAssistant.tenantId);
      const userId = Cookie.get("userId");
      let res=null
      let obj = JSON.parse(JSON.stringify(payload))
      obj.tenantId = tenantId;
      obj.userId = userId;
      delete obj.ai_sql;
      delete obj.resp_code;
      try{
        if(dialogFlag==="0"){
          res = yield call(tableDownload,obj)
        }else if(dialogFlag==="1"){
          if(payload?.resp_code==="00006"){
            res = yield call(tableDownloadKngc, {
              name:payload.kpi_name,
              kpi_sql :payload?.ai_sql ||"",
              tenantId :tenantId,
              userId :userId,
            })
          }else {
            res = yield call(tableDownloadKngc, obj)
          }
        }
        if(res&&res.fileData){
          downloadFileStream(res.fileData, payload.name+".xlsx")
        }else {
          message.error("文件下载失败")
        }
      }catch{
        //
      }
    },
    *fetchFileDownload({ payload }, { call }) {
     const res = yield call(filePreviewDownload,payload)
        if(res&&res.fileData){
          downloadFileStream(res.fileData, res.fileName)
        }else {
          message.error("文件下载失败")
        }
    },
    //    点击历史会话的某一条 请求聊天记录
    *fetchMessageList({ payload, callback }, { call, put,select }) {
      yield put({
        type: 'updateState',
        payload: {
          title:payload.title,
          dialogueId:payload.dialogueId
        }
      })
      const res = yield call(dialogueInfo, {
        sender:Cookie.get('userName'),
        id:payload.dialogueId
      })
      if(res&&res?.code===200){
        let dataList = res.data.length>0&&res.data.map(item=>{
          let feedInfo =  JSON.parse(item["robot-resp"]);
           feedInfo.index = Number(item["user-resp"])
           return feedInfo
        })||[]
        let pageFileList = []
          dataList.forEach(item=>{
            if(item.files){
              pageFileList = pageFileList.concat(item.files)
            }
        })
        let indexLast  =  dataList.findLastIndex(item=>item.character==="user")
        let pageContent = []
        if(indexLast>-1) {
          pageContent = dataList[indexLast+1]?.resp?.page_content||[]
        }
        yield put({
          type: 'updateState',
          payload:{
            dialogFlag:payload.dialogFlag,
            messageList:dataList,
            pageFileList:pageFileList,
            pageContent:pageContent,
          }
        })
        if (callback) callback();
      }else {
        yield put({
          type: 'updateState',
          payload: {
            dialogFlag:payload.dialogFlag||"0",
            messageList:[],
          }
        })
      }
    },
// 设置会话标题
    *updateDialogue({ payload,callback,noMsg }, { call,put,select }) {
      // const res = yield call(editDialogue,payload)
      let res=null
      try{
        res = yield call(editDialogue,payload)
      }catch{
        return
      }
      if(res&&res?.code===200){
        yield put({
          type:"updateState",
          payload:{
            title:payload.title,
          }
        })
        if(!noMsg) {
          // message.success("修改会话名称成功")
        }
        if (callback) callback(res?.code||400)
      }else {
        // message.error("修改会话名称失败")
      }
    },
    // 历史会话列表
    *fetchDialogueList({ payload,callback }, { call, put }) {
      // const res = yield call(dialogueList,payload)
      let res=null
      try{
        res = yield call(dialogueList,payload)
      }catch{
        return
      }
      if (res&&res?.code === 200) {
        yield put({
          type: 'updateState',
          payload: { dialogueList: res.data },
        });
        return res;
      }else {
        message.error("历史会话数据获取失败")
        yield put({
          type: 'updateState',
          payload: { dialogueList: [] },
        });
      }
    },


    *setDialogueId({ payload,callback }, { put }) {
      yield put({
        type: 'setDialogueId2',
        payload: payload,
      });
      if(callback) callback()
    },
    *fetchAddLog({ payload,callback }, { call, put,select }) {
      const dialogFlag = yield select(state => state.intellectAssistant.dialogFlag)
      let res=null
      if(payload.files) {
        payload.answer.files = payload.files.map(file=>({
          lastModified: file.lastModified,
          name: file.name,
          size: file.size,
          type: file.type,
          uid: file.uid,
          webkitRelativePath: file.webkitRelativePath
        }))
      }
     try {
        let params = {
          sender:payload.sender,
          dialogueId:payload.dialogueId,
          question:payload.question,
          answer:JSON.stringify(payload.answer),
          dialogFlag,
        }
       res = yield call(addDialogue,params)
       const id = yield select(state => state.intellectAssistant.dialogueId)
       if(id!==""){
         if(res&&res?.code===200){
           // 保证日志不会影响问答
           // let list = JSON.parse(payload.answer)
           let list = payload.answer
           if(list.character==="user"){
             yield put({
               type: 'fetchIndexPredictSearch',
               payload:{
                 name: JSON.parse(list.resp),
                 files:payload.files||undefined,
                 dialogueId:res.data?res.data:id
               },
             })
           }
           // 如果put之前没有对话id而且消息记录只有一条的时候才会设置调用callback设置会话名称
           if(!id&&callback) callback(res?.data?res.data:id)
         }else {
           yield put({
             type: 'updateState',
             payload: {
               isLoading:false,
             },
           })
         }
       }else {
         if(res&&res?.code===200){
           yield put({
             type: 'updateState',
             payload:{
               dialogueId:res.data?res.data:id,
             }
           })
           // 保证日志不会影响问答
           // let list = JSON.parse(payload.answer)
           let list = payload.answer
           console.log(payload,"payload")
           if(list.character==="user"){
             yield put({
               type: 'fetchIndexPredictSearch',
               payload:{
                 name: JSON.parse(list.resp),
                 dialogueId:res.data?res.data:id,
                 files:payload.files||undefined,
               },
             })
           }
           // 如果put之前没有对话id而且消息记录只有一条的时候才会设置调用callback设置会话名称
           if(!id&&callback) callback(res?.data?res.data:id)
         }else {
           yield put({
             type: 'updateState',
             payload: {
               isLoading:false,
             },
           })
         }
       }
     }catch (error){
       console.log(error,"eee")
       yield put({
         type: 'updateState',
         payload: {
           isLoading:false,
         },
       })
     }
    },
  },
  reducers: {
    //修改store中的会话id和会话名称
    changeDialogueId(state, { payload, callback }) {
      return {
        ...state,
        ...payload
      }
    },
    //添加消息列
    updateState(state, { payload ,callback}) {
      if(callback) callback()
      return {
        ...state,
        ...payload
      };
    },
    //添加消息列
    addMessageListState(state, { payload, callback,newCreateTime }) {
      let title = "新会话"
      if(state.messageList.length===0&&state.dialogueId===""){
        title =JSON.parse(payload.resp).replace(/\n|\\\\n/g, '');
      }else {
        title = state.title
      }
      let index = -1;
      if(newCreateTime) {
        index = state.messageList.findIndex(item=>{
          return item.createTime === newCreateTime;
        })
      }
      let realPayload={...payload,index:index>=0?index:state.messageList.length}
      //日志参数
      let params = {
        sender:Cookie.get('userName'),
        dialogueId:state.dialogueId,
        question:state.messageList.length,
        answer:realPayload,
        files:realPayload?.files?realPayload.files:undefined,
      }
      // console.log(params,"查询日志参数")
      if (callback) callback(params);
      if(index>=0){
        state.messageList.splice(index+1,0,realPayload)
      }else {
        state.messageList = state.messageList.concat(realPayload)
      }
      if(realPayload.files) {
        state.pageFileList = state.pageFileList.concat(realPayload.files)
      }
      return {
        ...state,
        title:title,
      };
    },
    setDialogueId2(state,{payload}){
      return {
        ...state,
        ...payload
      }
    }
  },
};
export default IntellectAssistant;
